<?php
/**
 * Created by 惠达浪
 * Email: crazys@126.com
 * Date: 2018/11/28
 * Time: 12:45
 */

namespace app\api\service;


use app\lib\enum\ErrorCodeEnum;
use app\lib\exception\TokenException;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use think\facade\Config;

/**
 * Class Token
 *
 * @package app\api\service
 */
class Token {
    /**
     * 生成令牌
     *
     * @param array $claims 附加信息
     *
     * @return \Lcobucci\JWT\Token
     */
    public function generateToken(array $claims = []) {
        $builder = new Builder();
        $signer = new Sha256();
        $expire_time = Config::get('global.token.expire');
        $jit = uniqid('user');

        //设置header和payload
        $builder->setIssuer("suspn.com")
            ->setAudience("api")
            ->setId($jit, true)
            ->setIssuedAt(time())
            ->setExpiration(time() + $expire_time)
            ->setNotBefore(time() + 1);
        //设置附加信息
        foreach ($claims as $key => $value) {
            $builder->set($key, $value);
        }

        // 对上面的信息使用sha256算法签名
        $builder->sign($signer, Config::get('global.token.salt'));
        // 获取生成的token
        $token = $builder->getToken();

        return $token;
    }


    /**
     * 根据token获取指定的信息
     *
     * @param string $token
     * @param string $key 需要获取的信息键名
     *
     * @return mixed 成功返回指定信息，失败返回false
     */
    public function getTokenVar($token, $key) {
        $tokenObj = $this->parseToken($token);
        if ($tokenObj) {
            return $tokenObj->getClaim($key);
        }
        return false;
    }

    /**
     * 核验令牌是否合法
     *
     * @param string|\Lcobucci\JWT\Token $token
     *
     * @return bool
     */
    public function verifyToken($token) {
        $tokenObj = $this->parseToken($token);

        if ($tokenObj) {
            $signer = new Sha256();
            $salt = Config::get('global.token.salt');

            //校验token
            if ($tokenObj->verify($signer, $salt) && !$tokenObj->isExpired()) {
                return true;
            }
        }

        return false;
    }


    /**
     * 解析令牌
     *
     * @param string|object $token 待解析的令牌
     *
     * @return mixed 解析成功返回令牌对象，失败返回false
     */
    private function parseToken($token) {
        if (is_string($token)) {
            //如果token中带有Bearer字样则去除
            if (strpos($token, 'Bearer ') === 0) {
                $token = str_replace('Bearer ', '', $token);
            }

            try {
                //解析token
                $Parser = new Parser();
                return $Parser->parse($token);
            } catch (\Exception $e) {
                return false;
            }
        }

        if ($token instanceof \Lcobucci\JWT\Token) {
            return $token;
        }

        return false;
    }

    /**
     * 使用令牌换取用户当前id
     *
     * @param string|\Lcobucci\JWT\Token $token 令牌
     *
     * @return bool|mixed
     */
    public function getUserIdByToken($token) {
        return $this->getTokenVar($token, 'uid');
    }

    /**
     * 使用令牌获取工作中心id
     *
     * @param string|\Lcobucci\JWT\Token $token 令牌
     *
     * @return mixed|bool
     */
    public function getWorkcenterIdByToken($token) {
        return $this->getTokenVar($token, 'wid');
    }
}